Skip to content

feat: unify Windows and Linux Coder Desktop in a single repo#173

Open
ibetitsmike wants to merge 3 commits into
mainfrom
mike/unify-linux-windows
Open

feat: unify Windows and Linux Coder Desktop in a single repo#173
ibetitsmike wants to merge 3 commits into
mainfrom
mike/unify-linux-windows

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Merges the coder-desktop-linux Avalonia port back into this repo so one codebase builds and ships Coder Desktop for both Windows and Linux, sharing the VPN service, RPC protocol, and SDKs.

What changed

  • Imported from coder-desktop-linux: App.Avalonia (Avalonia UI), App.Shared (UI-agnostic ViewModels/services), App.Linux (Linux service impls), Vpn.Linux (Unix socket RPC transports), Packaging.Linux (deb/rpm/tar/AUR scripts), scripts/run-linux-dev.sh, and the release-linux.yaml workflow.
  • Adopted platform-aware versions of shared sources (Vpn.Service/*, MutagenSdk/MutagenClient.cs, Vpn.DebugClient): runtime OS checks plus WINDOWS conditional compilation preserve existing Windows behavior. Only 27 existing files are touched, each with a focused diff.
  • Multi-targeted Vpn, Vpn.Service, Tests.Vpn, Tests.Vpn.Service as net8.0;net8.0-windows. ManagerRpc now uses an IRpcServerTransport abstraction: named pipes (extracted to NamedPipeServerTransport) on Windows, Unix domain sockets on Linux.
  • Added Coder.Desktop.Linux.slnf (excludes WinUI App, Tests.App, Installer), Directory.Build.props (EnableWindowsTargeting on non-Windows hosts only), and NuGet lock files for the new projects.
  • CI: Windows fmt/test/build jobs preserved (fmt passes the solution explicitly since the repo now has both a .sln and a .slnf); added test-linux and build-linux jobs.
  • Removed end_of_line = crlf from .editorconfig: the repo is stored with LF line endings and newer dotnet format versions treat the rule as a hard error, which would have forced a whole-repo whitespace rewrite. Existing file bytes are untouched.
  • Deflaked SpeakerTest.SendMessageWriteError (shutdown race, ~50% failure rate on Linux).
  • The WinUI App and Avalonia App.Avalonia/App.Shared remain separate; converging the Windows app onto App.Shared is follow-up work.

Validation

  • All 5 CI checks green: fmt, test-windows, build-windows, test-linux, build-linux.
  • Linux (local + fresh dev.coder.com aws-linux workspace): locked-mode restore of Coder.Desktop.Linux.slnf, Release build, all test projects green, format verification clean.
  • Linux end-to-end smoke on the workspace: ran CoderVpnService under sudo, drove it via Vpn.DebugClient over the Unix socket. VPN started against https://dev.coder.com, downloaded the tunnel binary, and streamed live workspace/agent peer updates with successful P2P handshakes.
  • Windows (dev.coder.com aws-windows-desktop workspace): full-solution restore, dotnet test -p:Platform=x64 on the shared test projects, Release publish of Vpn.Service (net8.0-windows). The WinUI App publish failures there reproduce identically on unmodified main (environment/SDK drift); CI is authoritative and passes.

This PR was prepared by Mux (AI agent) on behalf of Mike.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d8796feb52

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Vpn.Service/Manager.cs Outdated
Comment on lines +467 to +468
_logger.LogDebug(
"Skipping tunnel binary version validation: ProductVersion validation is only supported on Windows binaries");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Validate the Linux tunnel binary before executing it

On the Linux path this skips the only version validator, and TunnelBinarySignatureSigner defaults to empty on Linux, so the validator set is empty before the service chmods and executes the downloaded /bin/coder-linux-* as root. Because the RPC socket is made writable by all local users and StartRequest.CoderUrl is client-controlled, an unprivileged user can point the root service at a fake HTTP Coder endpoint and supply an arbitrary tunnel binary; Linux needs a trusted signature/checksum or equivalent client restriction before execution.

Useful? React with 👍 / 👎.

Comment thread App.Avalonia/App.axaml.cs Outdated
Comment on lines +106 to +109
foreach (var arg in args)
{
if (arg.Equals("--minimized", StringComparison.OrdinalIgnoreCase) ||
arg.Equals("--start-hidden", StringComparison.OrdinalIgnoreCase))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Dispatch coder:// launch arguments to the URI handler

The Linux desktop entry launches /usr/bin/coder-desktop %u, so opening a workspace app passes the coder://... URL in desktop.Args; this loop only recognizes minimized flags, and a repo-wide search shows IUriHandler is never registered or invoked by App.Avalonia. As a result, protocol activations on Linux just open the tray window and silently drop the RDP/open-workspace request.

Useful? React with 👍 / 👎.

Comment thread Packaging.Linux/PKGBUILD
rid='linux-arm64'
fi

local repo_root="${startdir}/.."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include the repo source in the AUR build inputs

When the generated AUR archive is built with makepkg, only the files declared in source are available, and this PKGBUILD declares just the service and desktop assets. ${startdir}/.. will not contain App.Avalonia or Vpn.Service in a normal AUR checkout, so both dotnet publish commands fail unless the full repository happens to be checked out next to the PKGBUILD; add a source tarball/git source or package the full source tree.

Useful? React with 👍 / 👎.

- Adopt platform-aware shared sources from coder-desktop-linux (runtime OS
  checks and WINDOWS conditional compilation preserve Windows behavior)
- Multi-target Vpn, Vpn.Service, Tests.Vpn, Tests.Vpn.Service as
  net8.0;net8.0-windows; Vpn.DebugClient becomes net8.0
- Add NamedPipeServerTransport (Windows) implementing IRpcServerTransport,
  extracted from the previous ManagerRpc named pipe server logic
- Add Directory.Build.props (EnableWindowsTargeting on non-Windows hosts;
  scoped because combining it with BuildWithNetFrameworkHostedCompiler on
  Windows CI breaks locked-mode restore)
- Add Linux projects to the solution plus Coder.Desktop.Linux.slnf filter,
  and pass the solution explicitly to dotnet format in CI
- Enable NuGet lock files for new projects and update affected locks
- CI: keep Windows fmt/test/build jobs, add Linux test and publish jobs
- Deflake SpeakerTest.SendMessageWriteError (shutdown race on Linux)
- Stop enforcing end_of_line in .editorconfig: the repo is stored with LF
  and newer dotnet format treats the CRLF rule as a hard error, turning
  every diff into whitespace churn
@ibetitsmike ibetitsmike force-pushed the mike/unify-linux-windows branch from 66b0323 to 2014f5c Compare July 5, 2026 20:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant